import { cloneDeep, isEqual } from "lodash-es";
import type { ColumnType } from "antd/es/table";
import type { BasicColumn, BasicTableProps, CellFormat, GetColumnsParams } from "../types/table";
import { ACTION_COLUMN_FLAG, DEFAULT_ALIGN, INDEX_COLUMN_FLAG } from "../const";
import { isArray, isBoolean, isFunction, isMap, isObject, isString } from "@/utils/is";
import { useEffect, useMemo, useState } from "react";
import moment from "moment";
import { renderEditCell } from "../components/editable";
import { deepMerge, nextTick } from "@/utils";

function handleItem(item: BasicColumn, ellipsis: boolean) {
	const { key, dataIndex, children } = item;
	item.align = item.align || DEFAULT_ALIGN;
	if (ellipsis) {
		if (!key) item.key = typeof dataIndex == "object" ? dataIndex.join("-") : dataIndex;

		if (!isBoolean(item.ellipsis)) {
			Object.assign(item, {
				ellipsis
			});
		}
	}
	if (children && children.length) handleChildren(children, !!ellipsis);
}

function handleChildren(children: BasicColumn[] | undefined, ellipsis: boolean) {
	if (!children) return;
	children.forEach(item => {
		const { children } = item;
		handleItem(item, ellipsis);
		handleChildren(children, ellipsis);
	});
}

// format cell
export function formatCell(text: string, format: CellFormat, record: Recordable, index: number) {
	if (!format) return text;

	// custom function
	if (isFunction(format)) return format(text, record, index);

	try {
		// date type
		const DATE_FORMAT_PREFIX = "date|";
		if (isString(format) && format.startsWith(DATE_FORMAT_PREFIX) && text) {
			const dateFormat = format.replace(DATE_FORMAT_PREFIX, "");

			if (!dateFormat) return text;

			return moment(text).format(dateFormat);
		}

		// Map
		if (isMap(format)) return format.get(text);
	} catch (error) {
		return text;
	}
}

// function handleActionColumn(propsRef: BasicTableProps, columns: BasicColumn[]) {
// 	const { actionColumn } = propsRef;
// 	if (!actionColumn) return;

// 	const hasIndex = columns.findIndex(column => column.flag === ACTION_COLUMN_FLAG);
// 	if (hasIndex === -1) {
// 		columns.push({
// 			...columns[hasIndex],
// 			fixed: "right",
// 			...actionColumn,
// 			flag: ACTION_COLUMN_FLAG
// 		});
// 	}
// }

export function useColumns(propsRef: BasicTableProps) {
	const [columnsRef, setColumnsRef] = useState(propsRef.columns);
	let cacheColumns = propsRef.columns;

	useEffect(() => {
		setColumnsRef(propsRef.columns);
		cacheColumns = propsRef.columns?.filter(item => !item.flag) ?? cacheColumns;
	}, [propsRef.columns]);

	const getColumnsRef = useMemo(() => {
		const columns = cloneDeep(columnsRef);

		// handleIndexColumn(propsRef, getPaginationRef, columns);
		// handleActionColumn(propsRef, columns);
		if (!columns) return [];

		const { ellipsis } = propsRef;

		columns.forEach((item: any) => {
			const { render, slots } = item;

			handleItem(item, Reflect.has(item, "ellipsis") ? !!item.ellipsis : !!ellipsis && !render && !slots);
		});
		return columns;
	}, [columnsRef]);

	function isIfShow(column: BasicColumn): boolean {
		const ifShow = column.ifShow;

		let isIfShow = true;

		if (isBoolean(ifShow)) isIfShow = ifShow;

		if (isFunction(ifShow)) isIfShow = ifShow(column);

		return isIfShow;
	}

	const getViewColumns = useMemo(() => {
		const viewColumns = getColumnsRef;

		const mapFn = (column: any) => {
			const { slots, render, format, edit, editRow, flag } = column;

			if (!slots || !slots?.title) column.customTitle = column.title;

			const isDefaultAction = [INDEX_COLUMN_FLAG, ACTION_COLUMN_FLAG].includes(flag!);
			if (!render && format && !edit && !isDefaultAction) {
				column.render = (text: any, record: any, index: any) => {
					return formatCell(text, format, record, index);
				};
			}

			// edit table
			if ((edit || editRow) && !isDefaultAction) column.render = renderEditCell(column);

			return column;
		};

		const columns = cloneDeep(viewColumns);
		return columns
			.filter(column => isIfShow(column))
			.map(column => {
				// Support table multiple header editable
				if (column.children?.length) column.children = column.children.map(mapFn);
				return mapFn(column);
			});
	}, [getColumnsRef]);

	function setCacheColumnsByField(dataIndex: string | undefined, value: Partial<BasicColumn>) {
		if (!dataIndex || !value) return;

		cacheColumns.forEach(item => {
			if (item.dataIndex === dataIndex) Object.assign(item, value);
		});
	}
	/**
	 * set columns
	 * @param columnList key｜column
	 */
	function setColumns(columnList: Partial<BasicColumn>[] | (string | string[])[]) {
		const columns = cloneDeep(columnList);
		if (!isArray(columns)) return;

		if (columns.length <= 0) {
			setColumnsRef([]);
			return;
		}

		const firstColumn = columns[0];

		const cacheKeys = cacheColumns.map(item => item.dataIndex);

		if (!isString(firstColumn) && !isArray(firstColumn)) {
			setColumnsRef(columns as BasicColumn[]);
		} else {
			const columnKeys = (columns as (string | string[])[]).map(m => m.toString());
			const newColumns: BasicColumn[] = [];
			cacheColumns.forEach(item => {
				newColumns.push({
					...item,
					defaultHidden: !columnKeys.includes(item.dataIndex?.toString() || (item.key as string))
				});
			});
			// Sort according to another array
			if (!isEqual(cacheKeys, columns)) {
				newColumns.sort((prev, next) => {
					return (
						columnKeys.indexOf(prev.dataIndex?.toString() as string) - columnKeys.indexOf(next.dataIndex?.toString() as string)
					);
				});
			}
			setColumnsRef(newColumns);
		}
	}

	function getColumns(opt?: GetColumnsParams) {
		const { ignoreIndex, ignoreAction } = opt || {};
		let columns = getColumnsRef;
		if (ignoreIndex) columns = columns.filter(item => item.flag !== INDEX_COLUMN_FLAG);

		if (ignoreAction) columns = columns.filter(item => item.flag !== ACTION_COLUMN_FLAG);

		return columns;
	}
	function getCacheColumns() {
		return cacheColumns;
	}
	function setCacheColumns(columns: BasicColumn[]) {
		if (!isArray(columns)) return;
		cacheColumns = columns.filter(item => !item.flag);
	}
	/**
	 * 拖拽列宽修改列的宽度
	 */
	function setColumnWidth(w: number, col: ColumnType<BasicColumn>) {
		col.width = w;
	}

	/**
	 * 修改列内容
	 */
	function updateColumn(col: ColumnType<BasicColumn> | ColumnType<BasicColumn>[]) {
		let updateColumns: ColumnType<BasicColumn>[] = [];
		if (isObject(col)) updateColumns.push(col as ColumnType<BasicColumn>);

		if (isArray(col)) updateColumns = [...col];

		const hasField = updateColumns.every(item => Reflect.has(item, "dataIndex"));

		if (!hasField) {
			console.error("All children of the BasicColumn array that need to be updated must contain the `dataIndex` field");
			return;
		}
		const columns: BasicColumn[] = [];
		nextTick(() => {
			// 必须异步，否则数据为空
			cacheColumns.forEach(val => {
				let _val;
				updateColumns.forEach(item => {
					if (val.dataIndex === item.dataIndex) _val = item;
				});
				if (_val !== undefined && val.dataIndex === _val.dataIndex) {
					const newSchema = deepMerge(val, _val);
					columns.push(newSchema as BasicColumn);
				} else {
					columns.push(val);
				}
			});
			setColumnsRef(columns);

			console.log("columns", cacheColumns, col);
		});
	}

	return {
		getColumnsRef,
		getCacheColumns,
		getColumns,
		setColumns,
		setColumnWidth,
		getViewColumns,
		setCacheColumnsByField,
		setCacheColumns,
		updateColumn
	};
}
